package com.tilaiedu.mvc.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.TimeZone;

/**
 * @Author xlzhang
 * @Date 2022/5/25 9:33
 * @Version 1.0
 * @Description TODO
 */
@Configuration
@ComponentScan("com.tilaiedu.mvc.controller")
// 开启springmvc的注解驱动，默认加载web应用的相关组件，比如消息转换器
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {

    // 配置日期格式转换
    // 这个配置只适用于普通参数转换(param+ form data)
    // json数据无论是响应还是请求，这个配置都没有用
    @Override
    public void addFormatters(FormatterRegistry registry) {
        // 配置Date类型的各种转换格式,只适用于Date日期格式
        final DateFormatter dateFormatter = new DateFormatter();
        dateFormatter.setFallbackPatterns("yyyy-MM-dd HH:mm:ss",
                "yyyy-MM-dd",
                "yyyy/MM/dd HH:mm:ss",
                "yyyy-MM-dd'T'HH:mm",
                "yyyy/MM/dd");
        registry.addFormatter(dateFormatter);

        // 配置JDK8的新日期API
        final DateTimeFormatterRegistrar formatterRegistrar =
                new DateTimeFormatterRegistrar();
        formatterRegistrar.setTimeFormatter(DateTimeFormatter.ofPattern("HH:mm:ss"));
        formatterRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        formatterRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        formatterRegistrar.registerFormatters(registry);
    }

    // 会覆盖系统的默认配置
    // @Override
    // public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    //
    // }

    private static final String TIME_ZONE = "GMT+8";
    private static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    private static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    // 这个接口会先执行系统默认的消息转换，再执行这里配置的自定义转换器
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof MappingJackson2HttpMessageConverter){
                // 初始化一个jackson的转换对象
                ObjectMapper objectMapper = new ObjectMapper();
                // 指定时区
                objectMapper.setTimeZone(TimeZone.getTimeZone(TIME_ZONE));
                // 日期类型字符串处理
                // 这里设置的是date类型的处理格式
                objectMapper.setDateFormat(new SimpleDateFormat(DEFAULT_DATETIME_PATTERN));
                // 设置参数为null时不序列化
                objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

                // Java8日期日期处理
                JavaTimeModule javaTimeModule = new JavaTimeModule();
                javaTimeModule.addSerializer(LocalDateTime.class,
                        new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATETIME_PATTERN)));
                javaTimeModule.addSerializer(LocalDate.class,
                        new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
                javaTimeModule.addSerializer(LocalTime.class,
                        new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

                javaTimeModule.addDeserializer(LocalDateTime.class,
                        new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATETIME_PATTERN)));
                javaTimeModule.addDeserializer(LocalDate.class,
                        new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
                javaTimeModule.addDeserializer(LocalTime.class,
                        new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

                objectMapper.registerModule(javaTimeModule);
                // 将配置好的objectMapper添加到消息转换器对象中
                ((MappingJackson2HttpMessageConverter) converter).setObjectMapper(objectMapper);
            }
        }
    }
}
